//
//  NetworkHelper.swift
//  iOSProjectExtensionSwift
//
//  Created by HBGG on 2020/7/17.
//  Copyright © 2020 lidianchao. All rights reserved.
//

import UIKit
import Alamofire
import SwiftyJSON
class NetworkHelper: NSObject {
    
    var isNetValiable = false
    
    private static let instance = NetworkHelper()
    class func sharedManager () ->NetworkHelper {
        instance.netChangedRegest()
        return instance
    }
    private func netChangedRegest() {
        let manager = NetworkReachabilityManager()
        if !manager!.isReachable {
            isNetValiable = false
        }
        if manager!.isReachableOnWWAN{
            isNetValiable = true
        }
        if manager!.isReachableOnEthernetOrWiFi {
            isNetValiable = true
        }
        manager?.startListening()
        
        if !isNetValiable {
            //通知全局网络不可用
        }
    }
    //不带 showHUD   不带 showError------>默认调用方法
    static func request(type:HTTPMethod, url:String, parameters:[String: String],responseOKCallback:@escaping(_ response:JSON) ->(),codeErrorCallback:@escaping(_ response:Any,_ errorNo:String) ->(),failureCallback:@escaping(_ error:Error) ->()) {
        request(type:type,url: url,parameters: parameters, showHUD: true, responseOKCallback: responseOKCallback, codeErrorCallback: codeErrorCallback, failureCallback: failureCallback,showError: true)
    }
    //带 showHUD   不带 showError
    static func request(type:HTTPMethod, url:String,parameters:[String: String],showHUD:Bool,responseOKCallback:@escaping(_ response:JSON) ->(),codeErrorCallback:@escaping(_ response:Any,_ errorNo:String) ->(),failureCallback:@escaping(_ error:Error) ->()) {
        request(type:type,url: url, parameters: parameters, showHUD: showHUD, responseOKCallback: responseOKCallback, codeErrorCallback: codeErrorCallback, failureCallback: failureCallback,showError: true)
    }
    //带 showError   不带 showHUD
    static func request(type:HTTPMethod, url:String, parameters:[String: String],responseOKCallback:@escaping(_ response:JSON) ->(),codeErrorCallback:@escaping(_ response:Any,_ errorNo:String) ->(),failureCallback:@escaping(_ error:Error) ->(),showError:Bool) {
        request(type:type,url: url, parameters: parameters, showHUD: true, responseOKCallback: responseOKCallback, codeErrorCallback: codeErrorCallback, failureCallback: failureCallback,showError: showError)
    }
    static func request(type:HTTPMethod, url:String,parameters:[String: String],showHUD:Bool,responseOKCallback:@escaping(_ response:JSON) ->(),codeErrorCallback:@escaping(_ response:Any,_ errorNo:String) ->(),failureCallback:@escaping(_ error:Error) ->(),showError:Bool) {
        let reachabilityManager = NetworkReachabilityManager(host: "www.apple.com")
        reachabilityManager?.listener = {status in
            if status == .notReachable || status == .notReachable {
                CBToast.showToastAction(message: "请检查网络连接")
                return
            }
        }
        if showHUD == true {
            DispatchQueue.main.async {
                CBToast.showToastAction()
            }
        }
        let header: Dictionary = ["token":UserDefaultsManager.getUsereToken()]
        Alamofire.request(url, method: type,parameters: parameters ,encoding: JSONEncoding.default, headers: header).responseJSON { (response) in
            if showHUD == true {
                DispatchQueue.main.async {
                    CBToast.hiddenToastAction()
                }
            }
            
            guard let jsonresult = response.result.value else {
                let error = response.result.error
                failureCallback(error!)
                urlFailureWithError(error:error!)
                return
            }
            NetworkHelper.validateResponseDataLegalityWithResponseData(responseData: jsonresult, responseOKCallback: responseOKCallback, codeErrorCallback: codeErrorCallback,showError: showError)
            reSetTimeoutCount()
        }
    }
    /// 下载文件---开始下载
    /// - Parameters:
    ///   - url: utl
    ///   - progressCallback: 下载进度回调
    ///   - successCallback: 下载成功回调
    ///   - failureCallback: 下载失败回调
    static func download(url:String,progressCallback:@escaping(_ progress:Progress) ->(), successCallback:@escaping(_ filePath:String) ->(),failureCallback:@escaping(_ error:Error, _ cancelledData:Data) ->()) {
        let token = UserDefaultsManager.getUsereToken()
        var header: Dictionary = ["":""]
        if token != "" {
             header = ["token":token]
        }
        
        Alamofire.download(url,parameters:header, to: { (url, response) -> (destinationURL: URL, options: DownloadRequest.DownloadOptions) in
            let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
            let fileURL = documentsURL.appendingPathComponent(response.suggestedFilename!)
            print("沙盒路径：\(documentsURL)")
            return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
        } ).downloadProgress(closure: { (progress: Progress) in
            print("当前进度:\(progress.fractionCompleted*100)%")
            progressCallback(progress)
        }).responseData { (response:DownloadResponse<Data>) in
            switch response.result {
            case .success( _):
                DispatchQueue.main.async {
                    print("路径:\(response.destinationURL!.path)")
                    successCallback(response.destinationURL!.path)
                }
                break
            case .failure(error:):
                //意外中止,返回错误信息及下载进度
                failureCallback(response.result.error!,response.resumeData!)
                break
            }
        }
    }
    /// 下载文件---断点续传
    /// - Parameters:
    ///   - cancelledData: 已下载数据
    ///   - progressCallback: 下载进度回调
    ///   - successCallback: 下载成功回调
    ///   - failureCallback: 下载失败回调
    static func download(cancelledData:Data, progressCallback:@escaping(_ progress:Progress) ->(), successCallback:@escaping(_ filePath:String) ->(),failureCallback:@escaping(_ error:Error, _ cancelledData:Data) ->()) {
        Alamofire.download(resumingWith: cancelledData, to: { (url, response) -> (destinationURL: URL, options: DownloadRequest.DownloadOptions) in
            let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
            let fileURL = documentsURL.appendingPathComponent(response.suggestedFilename!)
            print("沙盒路径：\(documentsURL)")
            return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
        }).downloadProgress(closure: { (progress: Progress) in
            print("当前进度:\(progress.fractionCompleted*100)%")
            progressCallback(progress)
        }).responseData { (response:DownloadResponse<Data>) in
            switch response.result {
            case .success( _):
                DispatchQueue.main.async {
                    print("路径:\(response.destinationURL!.path)")
                    successCallback(response.destinationURL!.path)
                }
                break
            case .failure(error:):
                //意外中止
                failureCallback(response.result.error!,response.resumeData!)
                break
            }
        }
    }
    static func upload(url:String,params:[String : String],image:UIImage,successCallback:@escaping(_ result: [String: Any]) ->(),failureCallback:@escaping(_ error:Error) ->()) {
        Alamofire.upload(multipartFormData: { (multipartFormData) in
            let data = image.jpegData(compressionQuality: 0.5)
            let fileName = String.init(describing: NSDate()) + ".png"
            // withName:：是根据文档决定传入的字符串
            multipartFormData.append(data!, withName: "name", fileName: fileName, mimeType: "image/png")
            for (key, value) in params {
                multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key)
            }
        }, to: url) { (encodingResult) in
            switch encodingResult {
            case .success(let upload,_,_):
                upload.responseJSON{response in
                    successCallback(response.result.value as! [String: Any])// 已经转为字典
                }
                break
            case .failure(let encodingError):
                failureCallback(encodingError)
                break
            }
        }
    }
    private static func validateResponseDataLegalityWithResponseData(responseData:Any,responseOKCallback:@escaping(_ response:JSON) ->(),codeErrorCallback:@escaping(_ response:Any,_ errorNo:String) ->(),showError:Bool) {
        let jsonData = JSON(responseData)
        
        if(jsonData.type != .dictionary) {
            //不是字典时，后台返回什么数据取什么数据
            codeErrorCallback(jsonData,"")
            return
        }
        let jsonDictory = jsonData.dictionary
        let isContains = jsonDictory?.keys.contains(RequestResponseCode)
        if(!isContains!) {
            //key既不包含code也不包含status，直接返回后台返回的数据
            codeErrorCallback(jsonData,"")
            return
        }
        
        let errorNo = jsonData[RequestResponseCode].int
        
        
        guard errorNo == 0 else {
            codeErrorCallback(jsonData,String(errorNo!))
            NetworkHelper.showAlerViewWithResponseDic(dic: jsonData, error: showError, requestResponseCodeStr:String(errorNo!))
            return
        }
        responseOKCallback(jsonData)
    }
    private static func showAlerViewWithResponseDic(dic:Any,error:Bool,requestResponseCodeStr:String) {
        if !(dic is Dictionary<String,Any>) {
            return
        }
        if requestResponseCodeStr == "1024" {
            //退出登录操作
            return
        }
        if error == true {
            if requestResponseCodeStr == RequestCorrectResponseCode
            {
                return;
            }
            let dicData = dic as! Dictionary<String,Any>
            if (dicData[RequestErrorMsg] is String) {
                let msg = dicData[RequestErrorMsg] as! NSString
                if(msg.length <= 0) {
                    return
                }
                CBToast.showToastAction(message: msg)
                return
            }
            if (dicData[RequestData] is String) {
                let msg = dicData[RequestData] as! NSString
                if(msg.length > 0) {
                    CBToast.showToastAction(message: msg)
                }
                return;
            }
        }
    }
    //在此处仅进行timeout错误码1001，来进行网络超时计数，达到20次，重新查看网络的连通性
    private static func urlFailureWithError(error:Error) {
        guard error._code == 1001 || error._code == -1001 || error._code == -999 else {
            return
        }
        let stand = UserDefaults.standard
        var count = stand.integer(forKey: "timeout_count")
        let time = stand.integer(forKey: "timeCurrent_error")
        //判断时间间隔2分钟
        if(count >= 20 && (getNowTimeTimestamp()-time)>2*60) {
            reSetTimeoutCount()
            stand.set(getNowTimeTimestamp(), forKey: "timeCurrent_error")
        }
        count+=1
        stand.set(count, forKey: "timeout_count")
        stand.synchronize()
    }
    private static func getNowTimeTimestamp() -> Int {
        let date = NSDate(timeIntervalSinceNow: 0)
        let iDate = date.timeIntervalSince1970
        return Int(iDate)
    }
    //重置计数
    private static func reSetTimeoutCount() {
        let stand = UserDefaults.standard
        stand.set(0,forKey: "timeout_count")
        stand.synchronize()
    }
}
